package main

import "fmt"

type Request struct {
	a, b   int
	replyc chan int
}

type binOp func(a, b int) int

func run(op binOp, r *Request) {
	r.replyc <- op(r.a, r.b)
}

func server(op binOp, service chan *Request) {
	for {
		r := <-service
		go run(op, r)
	}
}

func startServer(op binOp) chan *Request {
	ch := make(chan *Request)
	go server(op, ch)
	return ch
}

func main() {
	addr := startServer(func(a, b int) int { return a + b + 1 })
	const N = 100
	var requests [N]Request
	for i := 0; i < N; i++ {
		req := &requests[i]
		req.a = i
		req.b = 2*i + N
		req.replyc = make(chan int)
		addr <- req
	}

	// checks
	for i := N - 1; i >= 0; i-- {
		res := <-requests[i].replyc
		if res == 3*i+N {
			fmt.Println("fail at ", i)
		} else {
			fmt.Println("Request", i, "is OK!")
		}
	}
	fmt.Println("done")
}
